package com.jeecms.cms.action.member;

import com.jeecms.cms.api.ApiValidate;
import com.jeecms.cms.entity.assist.Branch;
import com.jeecms.cms.entity.assist.CmsEnterprise;
import com.jeecms.cms.entity.assist.CmsWebservice;
import com.jeecms.cms.manager.assist.CmsWebserviceMng;
import com.jeecms.cms.manager.main.BranchMng;
import com.jeecms.cms.manager.main.CmsEnterpriseMng;
import com.jeecms.cms.web.Token;
import com.jeecms.common.email.EmailSender;
import com.jeecms.common.email.MessageTemplate;
import com.jeecms.common.web.RequestUtils;
import com.jeecms.common.web.ResponseUtils;
import com.jeecms.common.web.session.SessionProvider;
import com.jeecms.common.web.springmvc.MessageResolver;
import com.jeecms.core.entity.*;
import com.jeecms.core.manager.CmsConfigItemMng;
import com.jeecms.core.manager.CmsUserMng;
import com.jeecms.core.manager.ConfigMng;
import com.jeecms.core.manager.UnifiedUserMng;
import com.jeecms.core.web.WebErrors;
import com.jeecms.core.web.util.CmsUtils;
import com.jeecms.core.web.util.FrontUtils;
import com.jeecms.plug.ali.sms.AliDySmsApi;
import com.octo.captcha.service.CaptchaServiceException;
import com.octo.captcha.service.image.ImageCaptchaService;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import static com.jeecms.cms.Constants.TPLDIR_MEMBER;

/**
 * 前台会员注册Action
 */
@Controller
public class RegisterAct {
	private static final Logger log = LoggerFactory
			.getLogger(RegisterAct.class);

	private static final String REGISTER = "tpl.register";
    private static final String REGISTER_RESULT = "tpl.registerResult";
    private static final String REGISTER_ACTIVE_SUCCESS = "tpl.registerActiveSuccess";
    private static final String LOGIN_INPUT = "tpl.loginInput";

	@Token(save=true)
	@RequestMapping(value = "/register.jspx", method = RequestMethod.GET)
	public String input(HttpServletRequest request,
			HttpServletResponse response, ModelMap model) {
		CmsSite site = CmsUtils.getSite(request);
		MemberConfig mcfg = site.getConfig().getMemberConfig();
		// 没有开启会员功能
		if (!mcfg.isMemberOn()) {
			return FrontUtils.showMessage(request, model, "member.memberClose");
		}
		// 没有开启会员注册
		if (!mcfg.isRegisterOn()) {
			return FrontUtils.showMessage(request, model,
					"member.registerClose");
		}
		List<CmsConfigItem>items=cmsConfigItemMng.getList(site.getConfig().getId(), CmsConfigItem.CATEGORY_REGISTER);
		FrontUtils.frontData(request, model, site);
		model.addAttribute("mcfg", mcfg);
		model.addAttribute("items", items);
		return FrontUtils.getTplPath(request, site.getSolutionPath(),
				TPLDIR_MEMBER, REGISTER);
	}

	/**
	 *
	 * @param username 用户手机号
	 * @param invitationCode 邀请码
	 * @param loginPassword 登录密码
	 * @param smCode  用户输入短信码
	 * @param validateCode 系统产生的短信验证码
	 * @param userExt '
	 * @param captcha 图片验证码
	 * @param nextUrl 下一个跳转页面
	 * @param request '
	 * @param response '
	 * @param model
	 * @return
	 * @throws IOException
	 */
	@Token(remove=true)
	@RequestMapping(value = "/register.jspx", method = RequestMethod.POST)
	public String submit(String username, String invitationCode,String email, Integer branchId, String loginPassword, String smCode, String validateCode,
			CmsUserExt userExt, String captcha, String nextUrl,
			HttpServletRequest request, HttpServletResponse response,
			ModelMap model) throws IOException {
		CmsSite site = CmsUtils.getSite(request);
		CmsConfig config = site.getConfig();
		WebErrors errors = validateSubmit(username, invitationCode, loginPassword, captcha, smCode, validateCode,
				site, request, response);
		boolean disabled=false;
		if(config.getMemberConfig().isCheckOn()){
			disabled=true;
		}
		if (errors.hasErrors()) {
			return FrontUtils.showError(request, response, model, errors);
		}
		String ip = RequestUtils.getIpAddr(request);
		Map<String,String>attrs=RequestUtils.getRequestMap(request, "attr_");
		if (config.getEmailValidate()) {
			EmailSender sender = configMng.getEmailSender();
			MessageTemplate msgTpl = configMng.getRegisterMessageTemplate();
			if (sender == null) {
				// 邮件服务器没有设置好
				model.addAttribute("status", 4);
			} else if (msgTpl == null) {
				// 邮件模板没有设置好
				model.addAttribute("status", 5);
			} else {
				try {
					cmsUserMng.registerMember(username, email, loginPassword, ip,
							null,disabled,userExt,attrs, false, sender, msgTpl);
					cmsWebserviceMng.callWebService("false",username, loginPassword, email, userExt,CmsWebservice.SERVICE_TYPE_ADD_USER);
					model.addAttribute("status", 0);
				} catch (UnsupportedEncodingException e) {
					// 发送邮件异常
					model.addAttribute("status", 100);
					model.addAttribute("message", e.getMessage());
					log.error("send email exception.", e);
				} catch (MessagingException e) {
					// 发送邮件异常
					model.addAttribute("status", 101);
					model.addAttribute("message", e.getMessage());
					log.error("send email exception.", e);
				}
			}
			log.info("member register success. username={}", username);
			FrontUtils.frontData(request, model, site);
			if (!StringUtils.isBlank(nextUrl)) {
				response.sendRedirect(nextUrl);
				return null;
			} else {
				return FrontUtils.getTplPath(request, site.getSolutionPath(),
						TPLDIR_MEMBER, REGISTER_RESULT);
			}
		} else {
            if(StringUtils.isNotBlank(invitationCode)) {
                userExt.setBranch(new Branch(branchId));
                //通过邀请码找到企业信息
                CmsEnterprise enterprise = cmsEnterpriseMng.getEnterpriseByInvitationCode(invitationCode);
                userExt.setEnterprise(enterprise);
                //注册成功后，将邀请码次数减1
                enterprise.setInvitationCount(enterprise.getInvitationCount() - 1);
                cmsEnterpriseMng.update(enterprise);
            }
			cmsUserMng.registerMember(username, email, loginPassword, ip, null,null,disabled,userExt,attrs,"","");
			cmsWebserviceMng.callWebService("false",username, loginPassword, "", userExt,CmsWebservice.SERVICE_TYPE_ADD_USER);
			log.info("member register success. username={}", username);
			FrontUtils.frontData(request, model, site);
			FrontUtils.frontPageData(request, model);
			model.addAttribute("success", true);
			return FrontUtils.getTplPath(request, site.getSolutionPath(),
					TPLDIR_MEMBER, LOGIN_INPUT);
		}
	}

	@RequestMapping(value = "/active.jspx", method = RequestMethod.GET)
	public String active(String username, String key,
			HttpServletRequest request, HttpServletResponse response,
			ModelMap model) throws IOException {
		CmsSite site = CmsUtils.getSite(request);
	    username = new String(request.getParameter("username").getBytes("iso8859-1"),"GBK");
		WebErrors errors = validateActive(username, key, request, response);
		if (errors.hasErrors()) {
			return FrontUtils.showError(request, response, model, errors);
		}
		unifiedUserMng.active(username, key);
		FrontUtils.frontData(request, model, site);
		return FrontUtils.getTplPath(request, site.getSolutionPath(),
				TPLDIR_MEMBER, REGISTER_ACTIVE_SUCCESS);
	}

	@RequestMapping(value = "/phone_unique.jspx")
	public void phoneUnique(HttpServletRequest request,
			HttpServletResponse response) {
		String username = RequestUtils.getQueryParam(request, "username");
		// 用户名为空，返回false。
		if (StringUtils.isBlank(username)) {
			ResponseUtils.renderJson(response, "false");
			return;
		}
		CmsSite site = CmsUtils.getSite(request);
		CmsConfig config = site.getConfig();
		// 保留字检查不通过，返回false。
		if (!config.getMemberConfig().checkUsernameReserved(username)) {
			ResponseUtils.renderJson(response, "false");
			return;
		}
		// 用户名存在，返回false。
		if (unifiedUserMng.usernameExist(username)) {
			ResponseUtils.renderJson(response, "false");
			return;
		}
		ResponseUtils.renderJson(response, "true");
	}


	@RequestMapping(value = "/phone_exists.jspx")
	public void phoneExists(HttpServletRequest request,
			HttpServletResponse response) {
		String phone = RequestUtils.getQueryParam(request, "username");
        JSONObject object = new JSONObject();
		// 用户名为空，返回false。
		if (StringUtils.isBlank(phone)) {
            object.put("flag", false);
			ResponseUtils.renderJson(response, object.toString());
			return;
		}

		// 用户名存在，true。
		if (!unifiedUserMng.usernameExist(phone)) {
            object.put("flag", false);
            object.put("errorMsg", "手机号未注册");
			ResponseUtils.renderJson(response, object.toString());
			return;
		}

        object.put("flag", true);
		ResponseUtils.renderJson(response, object.toString());
	}

	@RequestMapping(value = "/email_unique.jspx")
	public void emailUnique(HttpServletRequest request,
			HttpServletResponse response) {
		String email = RequestUtils.getQueryParam(request, "email");
		// email为空，返回false。
		if (StringUtils.isBlank(email)) {
			ResponseUtils.renderJson(response, "false");
			return;
		}
		// email存在，返回false。
		if (unifiedUserMng.emailExist(email)) {
			ResponseUtils.renderJson(response, "false");
			return;
		}
		ResponseUtils.renderJson(response, "true");
	}

    /**
     * 调用第三方短信服务，获取短信验证码
     * @param request '
     * @param response '
     */
	@RequestMapping(value = "/smCode_validate.jspx")
	public void smCodeValidate(HttpServletRequest request,
			HttpServletResponse response) {
		String phone = RequestUtils.getQueryParam(request, "phone");
		// smCode，返回false
		if (StringUtils.isBlank(phone)) {
			ResponseUtils.renderJson(response, "false");
			return;
		}

        Random ne=new Random();
		String smCode = String.valueOf(ne.nextInt(900000) + 100000);
        JSONObject object = new JSONObject();
        object.put("code", smCode);

        Map<String, Object> map = new HashMap<>();
        map.put("phone", phone);
        map.put("smsType", request.getParameter("smType"));
        map.put("smsContent", object.toString());
        try {
            //TODO	这里调用阿里云短信服务接口
            map = AliDySmsApi.getResponseResult(map);
            if(!"OK".equalsIgnoreCase(String.valueOf(map.get("code")))){
                object.put("errorMsg", map.get("Message"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        object.put("smCode", smCode);
        ResponseUtils.renderJson(response, object.toString());
	}

    /**
     * 根据邀请码获取企业信息
     * @param invitationCode  邀请码
     * @param response 返回企业信息和组织架构
     */
    @RequestMapping(value = "/findEnterpriseByInvite.jspx")
	public void findEnterpriseByInvite(String invitationCode, HttpServletRequest request, HttpServletResponse response){
        WebErrors errors = WebErrors.create(request);
        //验证公共非空参数
        errors= ApiValidate.validateRequiredParams(request,errors,  invitationCode);
        JSONObject object = new JSONObject();
        if(!errors.hasErrors()){
            CmsEnterprise enterprise = cmsEnterpriseMng.getEnterpriseByInvitationCode(invitationCode);
            if (enterprise == null || enterprise.getId() == null || enterprise.getInvitationCount() <= 0) {
                object.put("flag", false);
                object.put("errorMsg", "企业邀请码不存在或者邀请次数已用完！");
            }else{
                object.put("flag", true);
                object.put("enName", enterprise.getName());
                if(enterprise.getBranchs() != null && enterprise.getBranchs().size()>0){//把相同部门组织架构合并
                    JSONArray branchs = new JSONArray();
                    List<Object[]> enList = cmsEnterpriseMng.findBranchTreeForEn(enterprise.getId());
                    JSONArray firstLevel = new JSONArray();
                    JSONArray secondLevel = new JSONArray();
                    JSONArray thirdLevel = new JSONArray();
                    for(Object[] ce : enList){
                        org.json.JSONObject obj = new org.json.JSONObject();
                        if(ce[2] == null && ce[4] == null){//查询结果就是一级组织
                            obj.put("pid", ce[1]);
                            obj.put("id", ce[1]);
                            obj.put("name", ce[0]);
                            firstLevel.put(obj);
                        }else if(ce[4] == null) {//取二级组织和一级组织
                            org.json.JSONObject obj1 = new org.json.JSONObject();
                            obj1.put("pid", ce[2]);
                            obj1.put("id", ce[1]);
                            obj1.put("name", ce[0]);
                            secondLevel.put(obj1);

                            obj.put("pid", ce[2]);
                            obj.put("id", ce[2]);
                            obj.put("name", ce[3]);
                            firstLevel.put(obj);
                        }else if(ce[4] != null) {
                            org.json.JSONObject obj3 = new org.json.JSONObject();
                            obj3.put("pid", ce[2]);
                            obj3.put("id", ce[1]);
                            obj3.put("name", ce[0]);
                            thirdLevel.put(obj3);

                            org.json.JSONObject obj2 = new org.json.JSONObject();
                            obj2.put("pid", ce[4]);
                            obj2.put("id", ce[2]);
                            obj2.put("name", ce[3]);
                            secondLevel.put(obj2);

                            obj.put("pid", ce[4]);
                            obj.put("id", ce[4]);
                            obj.put("name", ce[5]);
                            firstLevel.put(obj);
                        }
                    }
                    firstLevel = delRepeatIndexid(firstLevel);
                    secondLevel = delRepeatIndexid(secondLevel);
                    thirdLevel = delRepeatIndexid(thirdLevel);
                    branchs.put(firstLevel.toString());
                    branchs.put(secondLevel.toString());
                    branchs.put(thirdLevel.toString());
                    object.put("branchList", branchs.toString());
                }
            }
        }else{
            object.put("flag", false);
            object.put("errorMsg","企业邀请码为必填项！");
        }
        ResponseUtils.renderJson(response, object.toString());
    }

	private WebErrors validateSubmit(String username, String invitationCode,
			String loginPassword, String captcha, String smCode, String validateCode, CmsSite site,
			HttpServletRequest request, HttpServletResponse response) {
		MemberConfig mcfg = site.getConfig().getMemberConfig();
		WebErrors errors = WebErrors.create(request);
		try {
			if (!imageCaptchaService.validateResponseForID(session
					.getSessionId(request, response), captcha)) {
				errors.addErrorCode("error.invalidCaptcha");
				return errors;
			}
		} catch (CaptchaServiceException e) {
			errors.addErrorCode("error.exceptionCaptcha");
			log.warn("", e);
			return errors;
		}
		if (errors.ifOutOfLength(username,MessageResolver.getMessage(request, "field.username"),
				mcfg.getUsernameMinLen(), 100, true)) {
			return errors;
		}
		if (errors.ifNotUsername(username,MessageResolver.getMessage(request, "field.username"),
				mcfg.getUsernameMinLen(), 100, true)) {
			return errors;
		}
		if (errors.ifOutOfLength(loginPassword, MessageResolver.getMessage(request, "field.password"),
				mcfg.getPasswordMinLen(), 100, true)) {
			return errors;
		}
		//短信验证码
		if (!smCode.equalsIgnoreCase(validateCode) ){
		    errors.addErrorCode("error.smCode", "smCode");
			return errors;
		}
		// 保留字检查不通过，返回false。
		if (!mcfg.checkUsernameReserved(username)) {
			errors.addErrorCode("error.usernameReserved");
			return errors;
		}
		// 用户名存在，返回false。
		if (unifiedUserMng.usernameExist(username)) {
			errors.addErrorCode("error.usernameExist");
			return errors;
		}
		return errors;
	}

	private WebErrors validateActive(String username, String activationCode,
			HttpServletRequest request, HttpServletResponse response) {
		WebErrors errors = WebErrors.create(request);
		if (StringUtils.isBlank(username)
				|| StringUtils.isBlank(activationCode)) {
			errors.addErrorCode("error.exceptionParams");
			return errors;
		}
		UnifiedUser user = unifiedUserMng.getByUsername(username);
		if (user == null) {
			errors.addErrorCode("error.usernameNotExist");
			return errors;
		}
		/*
		 * firefox访问链接二次访问，现简单不验证
		if (user.getActivation()
				|| StringUtils.isBlank(user.getActivationCode())) {
			errors.addErrorCode("error.usernameActivated");
			return errors;
		}
		if (!user.getActivationCode().equals(activationCode)) {
			errors.addErrorCode("error.exceptionActivationCode");
			return errors;
		}
		*/
		if (StringUtils.isNotBlank(user.getActivationCode())&&!user.getActivationCode().equals(activationCode)) {
			errors.addErrorCode("error.exceptionActivationCode");
			return errors;
		}
		return errors;
	}

    /**
     * 去重复index_id项合并value值
     * @param array
     */
    private static JSONArray delRepeatIndexid(JSONArray array) {
        JSONArray arrayTemp = new JSONArray();
        int num = 0;
        for(int i = 0;i < array.length();i++){
            if(num==0){
                arrayTemp.put(array.get(i));
            }else{
                int numJ = 0;
                for(int j = 0;j < arrayTemp.length(); j++){
                    org.json.JSONObject oldJson = (org.json.JSONObject)array.get(i);
                    org.json.JSONObject newJson = (org.json.JSONObject)arrayTemp.get(j);

                    String  pid1 = oldJson.get("pid").toString();
                    String  id2 = newJson.get("id").toString();

                    String  id = oldJson.get("id").toString();
                    String  name = oldJson.get("name").toString();

                    if(id.equals(id2)){
                        arrayTemp.remove(j);
                        org.json.JSONObject newObject = new org.json.JSONObject();
                        newObject.put("pid", pid1);
                        newObject.put("id", id);
                        newObject.put("name", name);
                        arrayTemp.put(newObject);
                        break;
                    }
                    numJ++;
                }
                if(numJ-1 == arrayTemp.length()-1){
                    arrayTemp.put(array.get(i));
                }
            }
            num++;
        }
        return arrayTemp;
    }

	@Autowired
	private CmsWebserviceMng cmsWebserviceMng;
	@Autowired
	private UnifiedUserMng unifiedUserMng;
	@Autowired
	private CmsUserMng cmsUserMng;
	@Autowired
	private SessionProvider session;
	@Autowired
	private ImageCaptchaService imageCaptchaService;
	@Autowired
	private ConfigMng configMng;
	@Autowired
	private CmsConfigItemMng cmsConfigItemMng;
    @Autowired
    private CmsEnterpriseMng cmsEnterpriseMng;
    @Autowired
    private BranchMng branchMng;
}
